﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DotNetCommon.Extensions
{
    /// <summary>
    /// <seealso cref="DateTime"/>的扩展类
    /// </summary>
    public static class DateTimeExtensions
    {
        /// <summary>
        /// 表示为 DateTime 的纪元
        /// </summary>
        internal static readonly DateTime Epoch;

        static DateTimeExtensions() => Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        /// <summary>
        /// 将给定的 <see cref="DateTime"/> 转换为Epoch的毫秒数。
        /// </summary>
        /// <param name="dateTime">给定的 <see cref="DateTime"/></param>
        /// <returns>自纪元以来的毫秒数</returns>
        public static long ToEpochMilliseconds(this DateTime dateTime) =>
            (long)dateTime.ToUniversalTime().Subtract(Epoch).TotalMilliseconds;

        /// <summary>
        ///将给定的 <see cref="DateTime"/> 转换为距纪元的秒。
        /// </summary>
        /// <param name="dateTime">给定的 <see cref="DateTime"/></param>
        /// <returns>Unix时间戳</returns>
        public static long ToEpochSeconds(this DateTime dateTime) =>
            dateTime.ToEpochMilliseconds() / 1000;

        /// <summary>
        /// 检查给定的日期是否在两个提供的日期之间
        /// <param name="date">给定的 <see cref="DateTime"/></param>
        /// <param name="startDate">开始日期 <see cref="DateTime"/></param>
        /// <param name="endDate">结束日期 <see cref="DateTime"/></param>
        /// <param name="compareTime">是否比较时间 <see cref="Boolean"/></param>
        /// </summary>
        public static bool IsBetween(this DateTime date, DateTime startDate, DateTime endDate, bool compareTime = false) =>
            compareTime ? date >= startDate && date <= endDate : date.Date >= startDate.Date && date.Date <= endDate.Date;

        /// <summary>
        /// 返回给定日期是否为该月的最后一天
        /// </summary>
        public static bool IsLastDayOfTheMonth(this DateTime dateTime) =>
            dateTime == new DateTime(dateTime.Year, dateTime.Month, 1).AddMonths(1).AddDays(-1);

        /// <summary>
        /// 返回给定日期是否位于周末(周六或周日)
        /// </summary>
        public static bool IsWeekend(this DateTime value) =>
            value.DayOfWeek == DayOfWeek.Sunday || value.DayOfWeek == DayOfWeek.Saturday;

        /// <summary>
        /// 确定给定年份是否为闰年。
        /// </summary>
        public static bool IsLeapYear(this DateTime value) =>
            DateTime.DaysInMonth(value.Year, 2) == 29;

        /// <summary>
        /// 返回基于 <paramref name="birthDay"/> 的年龄。
        /// </summary>
        /// <param name="birthDay">应计算年龄的生日</param>
        public static int Age(this DateTime birthDay)
        {
            var today = DateTime.Today;
            var age = today.Year - birthDay.Year;

            if (birthDay > today.AddYears(-age)) { age--; }
            return age;
        }

        /// <summary>
        /// 返回"yyyy-MM-dd HH:mm:ss.fff"格式的字符串
        /// </summary>
        /// <returns></returns>
        public static string ToCommonString(this DateTime value)
        {
            return value.ToString("yyyy-MM-dd HH:mm:ss.fff");
        }

        /// <summary>
        /// 返回"yyyy-MM-dd"格式的字符串
        /// </summary>
        /// <returns></returns>
        public static string ToCommonDateString(this DateTime value)
        {
            return value.ToString("yyyy-MM-dd");
        }

        /// <summary>
        /// 返回"yyyy-MM-dd HH:mm:ss"格式的字符串
        /// </summary>
        /// <returns></returns>
        public static string ToCommonDateTimeString(this DateTime value)
        {
            return value.ToString("yyyy-MM-dd HH:mm:ss");
        }
    }
}
